package com.study.talk.module.netty.handler;


import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.study.talk.common.util.JwtUtil;
import com.study.talk.common.util.RedisUtils;
import com.study.talk.common.util.SessionUtil;
import com.study.talk.common.util.TokenUtil;
import com.study.talk.module.entity.Friend;
import com.study.talk.module.entity.User;
import com.study.talk.module.entity.UserInfo;
import com.study.talk.module.netty.message.Session;
import com.study.talk.module.netty.message.request.LoginRequest;
import com.study.talk.module.netty.message.response.LoginResponse;
import com.study.talk.module.service.*;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

/**
 * 登录消息处理
 */

@Component
@ChannelHandler.Sharable
@Slf4j
public class LoginRequestHandler extends SimpleChannelInboundHandler<LoginRequest> {

    @Resource
    private UserService userService;

    @Resource
    private UserInfoService userInfoService;

    @Resource
    private GroupInfoService groupInfoService;

    @Resource
    private GroupUserInfoService groupUserInfoService;

    @Resource
    private FriendService friendService;

    @Resource
    private TokenUtil tokenUtil;

    @Resource
    private RedisUtils redisUtils;


    @Value("${jwt.expirationTime}")
    private long expiration;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, LoginRequest msg) throws Exception {
        log.info("登录事件,{}", msg);
        LoginResponse loginResponse = new LoginResponse();
        User user;
        if (!StringUtils.isBlank(msg.getToken())) {
            Integer userId = SessionUtil.getUserIdByToken(msg.getToken());
            user = userService.getById(userId);
            if (!ObjectUtils.isNotNull(user)) {
                loginResponse.setReason("认证失败，token错误或过期！");
                loginResponse.setSuccess(false);
                ctx.channel().writeAndFlush(loginResponse);
                return;
            }
        } else {
            if (StringUtils.isEmpty(msg.getUsername()) || StringUtils.isEmpty(msg.getPassword())) {
                loginResponse.setSuccess(false);
                loginResponse.setReason("用户名或密码不能为空");
                ctx.channel().writeAndFlush(loginResponse);
                return;
            } else {
                user = userService.getOne(new QueryWrapper<User>().eq("username", msg.getUsername()));
                if (!ObjectUtils.isNotNull(user) || !user.getPassword().equals(msg.getPassword())) {
                    loginResponse.setSuccess(false);
                    loginResponse.setReason("用户名或密码错误");
                    ctx.channel().writeAndFlush(loginResponse);
                    return;
                }
            }
        }
        UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("id", user.getId()));
        loginResponse.setGroupList(groupInfoService.getGroupListByUserId(user.getId()));
        loginResponse.setFriendList(friendService.getUserInfoList(user.getId()));


        loginResponse.setUsername(msg.getUsername());
        loginResponse.setDateTime(msg.getDateTime());
        loginResponse.setSuccess(true);
        loginResponse.setUserId(user.getId());
        loginResponse.setUser(user);
        loginResponse.setUserInfo(userInfo);


        String token = JwtUtil.getTokenUser(user);
        redisUtils.set(token, JSONUtil.toJsonStr(user), expiration, TimeUnit.DAYS);
        Authentication authentication = tokenUtil.getTokenAuthentication(user.getUsername());
        SecurityContextHolder.getContext().setAuthentication(authentication);

        loginResponse.setToken(token);
        //保存token
        SessionUtil.saveToken(user.getId(), token);
        //保存session，和channel关联
        SessionUtil.bindSession(new Session(user.getId(), userInfo.getNickName(), userInfo.getAvatar()), ctx.channel());

        /*if (msg.getFirst()) {
            log.info("first");
            loginResponse.messages = userService.getAllMessage(user.getId());
        }*/

        log.info("可写:{}", ctx.channel().isWritable());
        ctx.channel().writeAndFlush(loginResponse);
        log.info("消息发送:{}", loginResponse);

        //上线后直接发送消息
        /*if (msg.getSendMessageCache()) {
            userService.sendCacheMessage(user.getId(), ctx.channel());
        }*/
        //如果是首次登录则回复500条消息

    }
}
